package testSwing;

import flanagan.math.Fmath;
import flanagan.math.FourierTransform;
import flanagan.plot.PlotGraph;


public class PlotThread extends Thread {
	private double[]series;
	private double deltaT;
	private int chartType;
	private PlotGraph pg0;
	private FourierTransform ft0;
	private boolean mRemoveMean;
	private double[] timeData;

	public static final int GRAPH = 0;
	public static final int FOURIER = 1;
	public static final int POWER_SPECTRUM = 2;
	public static final int POWER_LOG = 3;
	public static final int INTEGRAL = 4;
	PlotThread(double [] pSeries, double pDeltaT, int pChartType) {
        this.series = pSeries;
        this.deltaT = pDeltaT;
        this.chartType = pChartType;
        preProcess();
    }

    private void preProcess() {

    	int nPoints = series.length;  // number of points
        timeData = new double[nPoints];
        double pointsPerCycle = deltaT;
        double deltaT = 1.0D/pointsPerCycle;

        for(int i=0; i<nPoints; i++){
             timeData[i]=i*deltaT;
        }

        switch (chartType) {
		case GRAPH:
			/*pg0 = new PlotGraph(timeData, series);
	        pg0.setGraphTitle("Title");
	        pg0.setXaxisLegend("time");
	        pg0.setXaxisUnitsName("s");
	        pg0.setXaxisLegend("y");
	        pg0.setCloseChoice(2);*/
			break;

		case FOURIER:

		case POWER_SPECTRUM:

		case POWER_LOG:

		case INTEGRAL:

			//ft0 = new FourierTransform(series);
			ft0 = new FourierTransform(series);
			ft0.setDeltaT(deltaT);
			break;

		default:
			break;
		}

	}

	private void removeMean() {
		double sum = 0;
		for (double val : series) {
			sum = sum + val;
		}

		double mean = sum / series.length;

		for (int i = 0; i < series.length; i++) {
			series[i] = series[i] - mean;
		}

	}

	public void run() {
		if(mRemoveMean && chartType!=GRAPH){
			removeMean();
			ft0.setData(series);
		}

		switch (chartType) {
		case GRAPH:
			/*pg0.setLine(3);
	        pg0.plot();
	        pg0.setCloseChoice(2);*/
	        new jFreeImplementation(timeData,series,"Input Data","","");
			break;

		case FOURIER:
	        ft0.transform();
	        double[] transformedData = ft0.getTransformedDataAsAlternate();
	        int k=0, nPoints = transformedData.length/2;
	        double [] ydata = new double[nPoints];
	        double[] tdata = new double[nPoints];
	        for(int i=0; i<nPoints; i++){
	            ydata[i] = transformedData[k]/nPoints;
	            k += 2;
	        }

	        tdata[0] = 0;
	        tdata[nPoints/2] = 1/(2*deltaT);
	        for(int i=1; i<nPoints/2; i++){
	            tdata[i] = (i)/(nPoints*deltaT);
	            tdata[nPoints-i] = -(i)/(nPoints*deltaT);
	        }

	       /* pg0 = new PlotGraph(tdata, ydata);
	        pg0.setGraphTitle("Fourier Transform");
	        pg0.setXaxisLegend("time");
	        pg0.setXaxisUnitsName("s");
	        pg0.setXaxisLegend("y");
	        pg0.setCloseChoice(2);
	        pg0.setLine(3);
	        pg0.plot();*/
	        new jFreeImplementation(tdata, ydata,"Fourier Transform","Frequency (Hz)","");
	        break;

		case POWER_SPECTRUM:
//			ft0.plotPowerSpectrum();

			double[][] powerSpectrum = ft0.powerSpectrum();
			/*checkNoise(powerSpectrum);
			pg0 = new PlotGraph(powerSpectrum[0],powerSpectrum[1]);
			pg0.setGraphTitle("Power Spectrum");
			pg0.setCloseChoice(2);
	        pg0.setLine(3);
	        pg0.setPoint(0);
	        pg0.plot();*/
			 new jFreeImplementation(powerSpectrum[0],powerSpectrum[1],"Estimation of Power Spectrum Density","Frequency (Hz)","");
			break;

		case POWER_LOG:
//			ft0.plotPowerLog();
			powerSpectrum = ft0.powerSpectrum();
			powerSpectrum= plotPowerSpectrumLog(0, powerSpectrum[0].length-1,powerSpectrum);
			new jFreeImplementation(powerSpectrum[0],powerSpectrum[1],"Log of Power Spectrum Density","Frequency (Hz)","");
			break;

		case INTEGRAL:
			powerSpectrum = ft0.powerSpectrum();
			checkNoise(powerSpectrum);
			double[] integralSum = new double[powerSpectrum[1].length];
			integralSum[0] = powerSpectrum[1][0];
			for (int i = 1; i < integralSum.length; i++) {
				integralSum[i] = integralSum[i-1] + powerSpectrum[1][i];
			}
//			pg0 = new PlotGraph(powerSpectrum[0],integralSum);
//			pg0.setCloseChoice(2);
//			pg0.setGraphTitle("Integral");
//	        pg0.setLine(3);
//	        pg0.setPoint(0);
//	        pg0.plot();
	        new jFreeImplementation(powerSpectrum[0],integralSum,"Integral Area of Power Spectrum","Frequency (Hz)","");
	        break;

		default:
			break;
		}



    }
	
	private double[][] plotPowerSpectrumLog(int low, int high, double[][] powerSpectrum){

	    int nData = powerSpectrum.length;
	    int nNew = high - low + 1;
        double[][] spectrum = new double[2][nNew];
        for(int i=0; i<nNew; i++){
            spectrum[0][i] = powerSpectrum[0][i+low];
            spectrum[1][i] = powerSpectrum[1][i+low];
        }

        // Find minimum of amplitudes that is not zero
        // find first non-zero value
        boolean test = true;
        int ii = 0;
        double minimum = 0.0D;
        while(test){
            if(spectrum[1][ii]>0.0D){
                minimum = spectrum[1][ii];
                test = false;
            }
            else{
                ii++;
                if(ii>=nNew){
                    test = false;
                    System.out.println("plotPowerSpectrumLog:  no non-zero amplitudes");
                    System.exit(0);
                }
            }
        }

        // Find minimum
        for(int i=ii+1; i<nNew; i++)if(spectrum[1][i]<minimum)minimum = spectrum[1][i];

        // Replace zeros with minimum
        for(int i=0; i<nNew; i++)if(spectrum[1][i]<=0.0D)spectrum[1][i] = minimum;

        // Take log to base 10
        for(int i=0; i<nNew; i++)spectrum[1][i] = Fmath.log10(spectrum[1][i]);

        // call display method
        String yLegend = "Log10(Mean Square Amplitude)";
        return spectrum;
}

	private void checkNoise(double[][] powerSpectrum) {
		if(!mRemoveMean){

			double lBandWidth = (powerSpectrum[0][1] -powerSpectrum[0][0]);
//			powerSpectrum[1][0] /= lBandWidth;
//			powerSpectrum[1][powerSpectrum[1].length-1] /= lBandWidth;
			powerSpectrum[1][0] = 0;
			for (int i = 1; i < powerSpectrum[1].length ; i++) {
				powerSpectrum[1][i] /= powerSpectrum[0][i];
			}
		}
	}

	public FourierTransform getFourier() {
		return ft0;
	}

	public void setRemoveMean(boolean pRemoveMean) {
		this.mRemoveMean = pRemoveMean;

	}
}

